AutoScan is a minimal, agentless security scanner built around SSH-based discovery, deterministic vcheck contracts, and a local CVE matching engine.
The project is designed to collect normalized host facts, evaluate vulnerability checks as small Python modules, and produce materialized findings suitable for later persistence or reporting. The current MVP focuses on base asset discovery and CVE detection using an NVD-derived SQLite database, CPE applicability logic, and local package-to-CPE mappings.
AutoScan is intended for authorized security assessment, internal inventory, vulnerability validation, and lab usage. Do not scan systems without explicit permission.
- Agentless remote execution over SSH.
- DB-backed target, credential, and SSH host key storage.
- SSH host key policies:
strict,accept_new,pin, andinsecure. - Minimal credential abstraction with support for password, key file, agent, inline test credentials, and external/unsupported secret providers.
- Bootstrap discovery for operating system and effective privileges.
- Base discovery collectors for host identity, kernel, packages, patches, services, listeners, users, and filesystem information.
- Contract-based vcheck execution with dependency resolution, result normalization, diagnostics, and finding materialization.
- CVE database population and incremental update from the NVD CVE API.
- Normalized CVE applicability schema preserving NVD configuration nodes, CPE matches, operators, negation, vulnerable flags, and version ranges.
cpe_mappingstable for DB-backed package/kernel/OS to CPE candidate resolution.- MVP CVE engine producing findings for package, kernel, and OS resources.
AutoScan is an MVP-stage project. The core scanning pipeline, discovery contracts, SSH security layer, CVE database schema, and CVE engine are functional, but the project intentionally remains small and does not yet provide a CLI, web UI, installer, or full reporting layer.
The CVE engine uses NVD CPE applicability data. On Linux distributions, package maintainers often backport security fixes while preserving upstream-looking versions. For this reason, Linux CVE findings based only on CPE matching should be treated as candidates requiring validation unless distro advisory support is added.
AutoScan/
├── contracts.py # Shared vcheck/result contracts and diagnostics
├── core.py # Top-level scan orchestration
├── scanner.py # Dependency resolver and vcheck executor
├── ssh_manager.py # SSH transport, command execution, host key enforcement
├── security_store.py # SQLite-backed targets, credentials, and SSH host keys
├── cve_db.py # NVD CVE database population, schema, and CPE mappings
├── cve_matcher.py # CVE applicability evaluator and finding builder
├── vchecks/ # Collector/check modules
│ ├── get_os.py
│ ├── get_privilege.py
│ ├── get_host.py
│ ├── get_kernel.py
│ ├── get_packages.py
│ ├── get_patches.py
│ ├── get_services.py
│ ├── get_listeners.py
│ ├── get_users.py
│ ├── get_filesystem.py
│ └── cve_engine.py
├── requirements.txt
└── LICENSE
- Python 3.10 or newer.
- Network access from the scanner host to target SSH services.
- Valid credentials for authorized targets.
asyncsshfor real SSH execution.- SQLite, included in the Python standard library.
Install Python dependencies:
cd AutoScan
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows PowerShell
pip install -r requirements.txtAutoScan currently exposes a Python API rather than a CLI. Run examples from the AutoScan/ directory so local module imports and the vchecks/ directory resolve correctly.
import asyncio
import os
from cve_db import CVEDB
async def main():
db = CVEDB("cve.db", nvd_api_key=os.getenv("NVD_API_KEY"))
await db.populate() # First full import
# await db.update() # Later incremental updates
asyncio.run(main())The CVE database uses these canonical tables:
cvescve_nodescve_cpe_matchescpe_mappings
No legacy flattened cpes table is used.
The CVE engine relies on cpe_mappings to map discovered resources to CPE candidates. A small fallback map exists for common software, but useful scans should seed explicit mappings.
from cve_db import CVEDB
cve_db = CVEDB("cve.db")
cve_db.upsert_cpe_mapping(
source_type="package",
source_name="openssl",
source_manager="dpkg",
part="a",
vendor="openssl",
product="openssl",
confidence=0.95,
notes="Debian/Ubuntu OpenSSL package",
)
cve_db.upsert_cpe_mapping(
source_type="kernel",
source_name="linux",
part="o",
vendor="linux",
product="linux_kernel",
confidence=0.90,
)source_type is expected to be one of package, kernel, or os for the current engine.
from security_store import CredentialStore, SQLiteStore, TargetStore
store = SQLiteStore("autoscan.db")
credentials = CredentialStore(store)
targets = TargetStore(store)
credentials.save({
"id": "linux-audit-key",
"label": "Linux audit SSH key",
"type": "key_file",
"username": "audit",
"secret_ref": "/absolute/path/to/id_ed25519",
})
targets.save({
"id": "lab-linux-01",
"host": "192.168.56.10",
"port": 22,
"username": "audit",
"credential_id": "linux-audit-key",
"host_key_policy": "accept_new",
})For production-like usage, prefer strict or pin host key policies after host keys have been trusted or pinned. accept_new is useful for lab bootstrap. insecure disables host key verification and should remain limited to disposable test environments.
import asyncio
import json
import os
from core import Core
os.environ["AUTOSCAN_CVE_DB"] = "cve.db"
targets = [{
"id": "lab-linux-01",
"host": "192.168.56.10",
"port": 22,
"username": "audit",
"credential_id": "linux-audit-key",
"host_key_policy": "accept_new",
}]
async def main():
core = Core(store_path="autoscan.db")
await core.initialize_and_screen(targets)
results = await core.start_scan()
print(json.dumps(results, indent=2))
asyncio.run(main())Each vcheck is a small Python module under vchecks/ with static metadata and an async run() function.
metadata = {
"contract_version": 1,
"type": "collector",
"family": "base",
"support": {"linux": ["any"], "windows": ["any"]},
"privilege": "user",
"requires": ["target", "ssh_manager", "get_os"],
"provides": {"get_example": 1},
}
async def run(target, ssh_manager, get_os):
...Vchecks return a standard result envelope:
{
"status": "ok",
"facts": {},
"findings": [],
"diagnostics": []
}Collector facts must be stored under the module name. For example, get_packages.py returns facts under facts["get_packages"].
Valid statuses are:
okpartialerrorskipped
Findings are materialized objects. They are not intended to be recomputed from facts on demand.
The CVE engine is implemented as vchecks/cve_engine.py and requires:
get_osget_kernelget_packagesget_patches
Database discovery order:
AUTOSCAN_CVE_DB, when set../cve.db, when present.skippedresult with diagnosticcve_db_missing.
The engine performs:
- Resource candidate generation from OS, kernel, and package facts.
- Mapping through
cpe_mappingsplus a conservative fallback map. - CVE candidate prefiltering by CPE
part,vendor, andproduct. - NVD node evaluation with
AND,OR,negate,vulnerable, and version range semantics. - Finding generation with deterministic fingerprints and evidence.
Example finding fingerprint:
cve_engine|pkg:dpkg:openssl:amd64|CVE-2026-1234
AutoScan avoids using the local OpenSSH user configuration as the canonical trust source. Targets, credentials, and SSH host keys are stored in the AutoScan SQLite store.
Credential secrets should not be committed to source control. For real deployments, use environment-backed secrets or an external secret provider. The current db_encrypted mode is reserved by contract but intentionally not implemented with custom cryptography.
The project intentionally favors simple Python modules and explicit contracts over a plugin framework. Before adding new features, keep these invariants stable:
- vcheck metadata must be statically readable;
requiresmust matchrun()parameters;- collector facts must use the collector module name as namespace;
- findings must be materialized in scan results;
- transport/security logic must stay outside vchecks;
- CVE/CPE database schema must preserve NVD configuration node semantics.
Compile check:
python -m py_compile *.py vchecks/*.py- No CLI yet.
- No built-in report renderer yet.
- No persistence layer for scan results yet.
- Linux distro advisory correlation is not implemented yet.
- CVE confidence depends heavily on mapping quality and package/version semantics.
- Real SSH execution requires
asyncssh; local import tests can run without it.
AutoScan is licensed under the GNU General Public License v3.0. See LICENSE.